package com.gonsin.ta.logic.parse.operator;

import cn.hutool.core.util.ArrayUtil;
import com.gonsin.ta.logic.exceptions.TaException;
import com.gonsin.ta.logic.parse.Chain;
import com.gonsin.ta.logic.parse.condition.Executable;
import com.gonsin.ta.logic.parse.condition.FutureCondition;
import com.gonsin.ta.logic.parse.condition.WaitCondition;
import com.ql.util.express.*;
import com.ql.util.express.config.QLExpressRunStrategy;
import com.ql.util.express.exception.QLException;
import com.ql.util.express.instruction.OperateDataCacheManager;
import com.ql.util.express.instruction.op.OperatorBase;
import com.ql.util.express.instruction.opdata.OperateDataAttr;

import java.util.ArrayList;
import java.util.List;

/**
 * 运行节点
 */
public class ThenOperator extends OperatorBase {

    private Chain chain;

    public ThenOperator(Chain chain) {
        this.chain = chain;
    }

    public WaitCondition executeInner(Object[] objects, InstructionSetContext parent, ArraySwap list) throws Exception {

        validate(objects);

        WaitCondition waitCondition = (WaitCondition) objects[0];
        List<Executable> next = new ArrayList<>();
        for (int i = 1; i < objects.length; i++) {
            if (objects[i] instanceof Executable) {
                Executable target = (Executable) objects[i];
                next.add(target);
            }else {
                OperateData operateData = list.get(i);
                OperateDataAttr attr = (OperateDataAttr)operateData;
                String conditionName = attr.getName();
                Object symbolGet = parent.getSymbol(conditionName);
                if(symbolGet != null){
                    FutureCondition condition = new FutureCondition();
                    condition.setConditionName(conditionName);
                    next.add(condition);
                } else {
                    throw new TaException("chain id = {}, THEN方法里找不到 【{}】", chain.getChainId(), conditionName);
                }
                throw new TaException("chain id = {}, THEN方法的参数必须是节点或者流程", chain.getChainId());
            }
        }
        waitCondition.setNext(next);
        return waitCondition;
    }

    private void validate(Object[] objects){
        if (ArrayUtil.isEmpty(objects)){
            throw new TaException("chain id = {}, THEN方法必须至少包含一个参数", chain.getChainId());
        }

        if (objects.length == 1){
            throw new TaException("chain id = {}, THEN方法必须至少包含一个参数", chain.getChainId());
        }

        if(!(objects[0] instanceof WaitCondition)){
            throw new TaException("chain id = {}, THEN必须在WAIT方法之后调用", chain.getChainId());
        }
    }


    @Override
    public OperateData executeInner(InstructionSetContext parent, ArraySwap list) throws Exception {
        Object[] parameters = new Object[list.length];
        for (int i = 0; i < list.length; i++) {
            if (list.get(i) == null && QLExpressRunStrategy.isAvoidNullPointer()) {
                parameters[i] = null;
            } else {
                parameters[i] = list.get(i).getObject(parent);
            }
        }
        Object result = this.executeInner(parameters, parent, list);
        if (result != null && result.getClass().equals(OperateData.class)) {
            throw new QLException("操作符号定义的返回类型错误：" + this.getAliasName());
        }
        if (result == null) {
            //return new OperateData(null,null);
            return OperateDataCacheManager.fetchOperateData(null, null);
        } else {
            //return new OperateData(result,ExpressUtil.getSimpleDataType(result.getClass()));
            return OperateDataCacheManager.fetchOperateData(result, ExpressUtil.getSimpleDataType(result.getClass()));
        }
    }
}
